// FunctionalCompositeCommand.java
package org.zjx.command;

import lombok.extern.slf4j.Slf4j;
import org.zjx.core.IWindow;
import org.zjx.state.StateManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 函数式复合命令 - 支持延迟执行和结果提取
 */
@Slf4j
public abstract class CompositeCommand extends Command {
    private final List<CommandStep> steps;
    private final Map<String, Object> context;

    public CompositeCommand(IWindow window, StateManager stateManager) {
        super(window, false, stateManager);
        this.steps = new ArrayList<>();
        this.context = new HashMap<>();
        initializeSubCommands();
    }


    protected abstract void initializeSubCommands();


    /**
     * 添加固定命令
     */
    public void add(Command command) {
        steps.add(new FixedStep(command));
    }

    /**
     * 添加动态命令（可以访问上下文）
     */
    public void addDynamic(Function<Map<String, Object>, Command> commandFactory) {
        steps.add(new DynamicStep(commandFactory));
    }

    /**
     * 添加带结果保存的命令（立即创建）
     */
    public void addWithResult(Command command, String resultKey, Function<Command, Object> resultMapper) {
        steps.add(new ResultStep(command, resultKey, resultMapper));
    }

    /**
     * 添加带结果保存的命令（延迟创建，解决覆盖问题）
     */
    public void addWithResult(Supplier<Command> commandSupplier, String resultKey, Function<Command, Object> resultMapper) {
        steps.add(new LazyResultStep(commandSupplier, resultKey, resultMapper));
    }

    @Override
    protected void doExecute() throws Exception {
        log.info("[动态命令] 开始执行: {} ({}个步骤)", getCommandName(), steps.size());

        for (int i = 0; i < steps.size(); i++) {
            checkInterruption();
            log.info("[动态命令] 执行步骤 {}/{}", i + 1, steps.size());

            CommandStep step = steps.get(i);
            Command command = step.createCommand(context);

            if (command == null) throw new RuntimeException("步骤 " + (i + 1) + " 生成命令为null");

            boolean success = command.execute();
            if (!success) {
                if (isInterrupted()) throw new InterruptedException("命令执行被中断");
                throw new RuntimeException("步骤执行失败: " + command.getCommandName());
            }

            step.saveResult(command, context);
        }

        log.info("[动态命令] 完成: {}", getCommandName());
    }

    /**
     * 设置上下文数据
     */
    public void set(String key, Object value) {
        context.put(key, value);
    }

    /**
     * 获取上下文数据
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key) {
        return (T) context.get(key);
    }

    /**
     * 清空上下文数据
     */
    public void clearContext() {
        context.clear();
    }

    // 步骤接口
    private interface CommandStep {
        Command createCommand(Map<String, Object> context) throws Exception;

        void saveResult(Command command, Map<String, Object> context) throws Exception;
    }

    // 固定步骤
    private static class FixedStep implements CommandStep {
        private final Command command;

        FixedStep(Command command) {
            this.command = command;
        }

        @Override
        public Command createCommand(Map<String, Object> context) {
            return command;
        }

        @Override
        public void saveResult(Command command, Map<String, Object> context) {
        }
    }

    // 动态步骤
    private static class DynamicStep implements CommandStep {
        private final Function<Map<String, Object>, Command> factory;

        DynamicStep(Function<Map<String, Object>, Command> factory) {
            this.factory = factory;
        }

        @Override
        public Command createCommand(Map<String, Object> context) {
            return factory.apply(context);
        }

        @Override
        public void saveResult(Command command, Map<String, Object> context) {
        }
    }

    // 结果步骤（立即创建）
    private static class ResultStep implements CommandStep {
        private final Command command;
        private final String resultKey;
        private final Function<Command, Object> resultMapper;

        ResultStep(Command command, String resultKey, Function<Command, Object> resultMapper) {
            this.command = command;
            this.resultKey = resultKey;
            this.resultMapper = resultMapper;
        }

        @Override
        public Command createCommand(Map<String, Object> context) {
            return command;
        }

        @Override
        public void saveResult(Command command, Map<String, Object> context) {
            if (resultKey != null && resultMapper != null) {
                Object result = resultMapper.apply(command);
                context.put(resultKey, result);
            }
        }
    }

    // 延迟结果步骤（解决覆盖问题）
    private static class LazyResultStep implements CommandStep {
        private final Supplier<Command> commandSupplier;
        private final String resultKey;
        private final Function<Command, Object> resultMapper;

        LazyResultStep(Supplier<Command> commandSupplier, String resultKey,
                       Function<Command, Object> resultMapper) {
            this.commandSupplier = commandSupplier;
            this.resultKey = resultKey;
            this.resultMapper = resultMapper;
        }

        @Override
        public Command createCommand(Map<String, Object> context) {
            return commandSupplier.get(); // 每次执行时创建新实例
        }

        @Override
        public void saveResult(Command command, Map<String, Object> context) {
            if (resultKey != null && resultMapper != null) {
                Object result = resultMapper.apply(command);
                context.put(resultKey, result);
            }
        }
    }
}